package com.woniuxy.qiantai.interceptors;

import com.woniuxy.qiantai.utils.CookieUtils;
import com.woniuxy.qiantai.utils.JwtUtils;
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.TimeUnit;

@Component
public class JwtRenewInterceptor implements HandlerInterceptor {

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//        return HandlerInterceptor.super.preHandle(request, response, handler);
        /*
        续期: 在interceptor中 读取request里的token,如果发现过期,那就去访问下redis中的关联数据,
            如果关联数据尚未过期,那就重新生成token,并更新redis中的关联数据
            如果关联数据已经过期,那就不再续期.  这种情况就是登录状态过期.
         */
        //做jwt续期操作
        System.out.println("拦截");
        String userTokenFromCookie = "";
        try {
            //尝试从request中正常解析出account
            userTokenFromCookie = CookieUtils.getUserTokenFromCookie(request);
            System.out.println("--------------------------续期前的freshToken：" + userTokenFromCookie);
            String account = JwtUtils.getAccount(userTokenFromCookie);
        } catch (Exception e) {
            //解析jwtToken时发生了过期异常
            //接下来需要进行确定是否要对这个过期的token进行续期
            if (!StringUtils.isEmpty(userTokenFromCookie)) {
                ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
                //获取redis中的关联数据
                String accountFromRedis = operations.get(userTokenFromCookie);
                if (!StringUtils.isEmpty(accountFromRedis)) {  //只有在redis中的关联数据也没有过期时才进行续期操作
                    //当redis中的关联数据还没过期的时候我们才去对token进行续期
                    System.out.println("---------------------------token过期更新token,执行续期操作");
                    //
                    String freshToken = JwtUtils.createToken(accountFromRedis, 15);
                    CookieUtils.setUserToken2Cookie(response, freshToken);
                    System.out.println("--------------------------续期后的freshToken：" + freshToken);

                    //更新token在redis中的关联数据
                    stringRedisTemplate.delete(userTokenFromCookie);
                    operations.set(freshToken, accountFromRedis, 30, TimeUnit.MINUTES);
                    System.out.println("---------------------------续期操作完成！");
                } else {
                    System.out.println("---------------------------redis中的token过期！");
                    request.getRequestDispatcher("/login.html").forward(request, response);
                    return false;
                }
            } else {
                System.out.println("---------------------------cookie中的token为null！");
                request.getRequestDispatcher("/login.html").forward(request, response);
                return false;
            }
        }
        return true;
    }
}
